package br.com.duosoftware.orcamento.managedbeans;

import br.com.duosoftware.orcamento.daos.AcaoDAO;
import br.com.duosoftware.orcamento.daos.FormaDeImplementacaoDaAcaoDAO;
import br.com.duosoftware.orcamento.daos.GestorDAO;
import br.com.duosoftware.orcamento.daos.SubFuncaoDAO;
import br.com.duosoftware.orcamento.daos.TipoDeAcaoDAO;
import br.com.duosoftware.orcamento.daos.UnidadeDeMedidaDAO;
import br.com.duosoftware.orcamento.daos.UnidadeOrcamentariaDAO;
import br.com.duosoftware.orcamento.entidades.Acao;
import br.com.duosoftware.orcamento.entidades.FormaDeImplementacaoDaAcao;
import br.com.duosoftware.orcamento.entidades.Gestor;
import br.com.duosoftware.orcamento.entidades.PeriodoDePrograma;
import br.com.duosoftware.orcamento.entidades.Programa;
import br.com.duosoftware.orcamento.entidades.ProgramaPeriodo;
import br.com.duosoftware.orcamento.entidades.SubFuncao;
import br.com.duosoftware.orcamento.entidades.TipoDeAcao;
import br.com.duosoftware.orcamento.entidades.UnidadeDeMedida;
import br.com.duosoftware.orcamento.entidades.UnidadeOrcamentaria;
import br.com.duosoftware.orcamento.utils.ManagedBeanUtil;
import br.com.duosoftware.orcamento.utils.Mensagens;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import org.hibernate.exception.ConstraintViolationException;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Daniel
 *
 */
@ManagedBean
@ViewScoped
public class AcaoBean implements Serializable {

    private Acao acao;
    private AcaoDAO acaoDAO;
    private List<Acao> acoes;
    //
    private ProgramaBean programaBean;
    private ProgramaPeriodoBean programaPeriodoBean;
    //
    //************SelectItens***********************
    private List<SelectItem> tiposAcao;
    private List<SelectItem> formasImplementacaoDaAcao;
    private List<SelectItem> unidadesOrcamentarias;
    private List<SelectItem> gestores;
    private List<SelectItem> unidadesDeMedida;
    private List<SelectItem> subFuncoes;
    //**********************************************

    public AcaoBean() {

        programaBean = (ProgramaBean) ManagedBeanUtil.getContextInfo("#{programaBean}");

        programaPeriodoBean = (ProgramaPeriodoBean) ManagedBeanUtil.getContextInfo("#{programaPeriodoBean}");

        acaoDAO = new AcaoDAO();

    }

    public Acao getAcao() {
        return acao;
    }

    public void setAcao(Acao acao) {
        this.acao = acao;
    }

    public List<Acao> getAcoes() {
        return acoes;
    }

    public void setAcoes(List<Acao> acoes) {
        this.acoes = acoes;
    }

    //
    //Chamado no evento SelectItem da Tabela Períodos
    //
    public void buscarAcoesPorPeriodoDePrograma() {

        Programa programa = programaBean.getPrograma();

        ProgramaPeriodo programaPeriodo = programaPeriodoBean.getProgramaPeriodo();

        if (programaPeriodo != null && programaPeriodo.getId() != null) {
            acoes = acaoDAO.listarAcoes(programa, programaPeriodo.getPeriodoDePrograma());
        } else {
            acoes = null;
        }

        /*
        
         faz com que a tabela de Previsões, na página Programa.xhtml seja limpada,
         caso não seja retornada nenhuma ação
        
         */
        if (acoes == null || acoes.isEmpty()) {
            acao = new Acao();
        }

    }

    /**
     * <b>Método que inicializa a acao a ser cadastrado.</b><p>
     *
     * @return void
     *
     */
    public void adicionarInicio() {

        ProgramaPeriodo programaPeriodo = programaPeriodoBean.getProgramaPeriodo();

        if (programaPeriodo != null) {

            PeriodoDePrograma periodoDePrograma
                    = programaPeriodoBean.getProgramaPeriodo().getPeriodoDePrograma();

            acao = new Acao();

            Integer max = acaoDAO.getMaxNumeroAcao();

            acao.setNumeroAcao(String.format("%04d", max != null ? max + 1 : 1));
            acao.setPrograma(programaBean.getPrograma());
            acao.setPeriodoDePrograma(periodoDePrograma);

            RequestContext.getCurrentInstance().execute("dlgAcao.show()");

        } else {

            Mensagens.mensagemDeAlerta("Selecione um período",
                                       "Selecione um período");

        }

    }

    /**
     * <b>Método que adiciona ou edita uma Acao</b><p>
     *
     * Após o término o método fecha o dialog de cadastro.
     * <p/>
     *
     * @return void
     *
     */
    public void adicionarEditarFim() {

        //Se estiver cadastrando uma nova acao, e não editando, gera um código.
        if (acao.getId() == null) {

            Integer max = acaoDAO.getMaxNumeroAcao();
            acao.setNumeroAcao(String.format("%04d", max != null ? max + 1 : 1));

        }

        acaoDAO.salvarOuAtualizar(acao);
        acao = new Acao();
        acoes = null;

        buscarAcoesPorPeriodoDePrograma();
        
        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.execute("dlgAcao.hide()");
        requestContext.update("formProgramas:dtAcoes");

    }

    /**
     * <b>Método para iniciar o processo de edição de um Acao.</b>
     * <p>
     *
     * Ele verifica se há um Acao selecionada para edição, se não houver é
     * emitida uma mensagem pedindo que o usuário selecione uma.<p>
     *
     * Caso haja um Acao selecionado o médoto abre o dialog para edição<p>
     *
     * @return void
     *
     */
    public void editarInicio() {

        if (acao == null) {

            Mensagens.mensagemDeAlerta("Selecione um registro", "Selecione um re"
                    + "gistro para Editar");

        } else {

            RequestContext.getCurrentInstance().execute("dlgAcao.show()");

        }

    }

    /**
     * <b>Método para iniciar o processo de exclusão de um Acao.</b>
     * <p>
     *
     * Ele verifica se há uma Acao selecionado para exclusão, se não houver é
     * emitida uma mensagem pedindo que o usuário selecione uma.<p>
     *
     * Caso haja um Acao selecionado o médoto abre um p:dialog para confirma ção
     * da exclusão.<p>
     *
     * @return void
     *
     */
    public void excluirInicio() {

        if (acao == null) {
            Mensagens.mensagemDeAlerta("Selecione um registro",
                    "Selecione um registro para excluir");
        } else {
            RequestContext.getCurrentInstance()
                    .execute("dlgExcluirAcao.show()");
        }

    }

    /**
     * <b>Método para excluir um Acao.</b>
     * <p>
     *
     * Ele verifica se a Acao selecionado para exclusão está sendo utilizado por
     * alguma outra tabela do banco. Se estiver uma mensagem de aviso é dada ao
     * usuário<p>
     *
     * @return void
     *
     */
    public void excluirFim() {

        try {

            acaoDAO.excluir(acao);
            acao = new Acao();
            acoes = null;
            
            buscarAcoesPorPeriodoDePrograma();

        } catch (ConstraintViolationException e) {
            Mensagens.mensagemDeAlerta("Registro Utilizado",
                                       "Esse registro está sendo utilizado");
        }

        RequestContext.getCurrentInstance().execute("dlgExcluirAcao.hide()");

    }

    /**
     * <b> Método para cancelar uma operação de cadastro ou edição.</b>
     * <p>
     *
     * O método instancia um novo objeto na variável Acao para limpar as
     * infomações.<p>
     *
     * @return void
     */
    public void cancelar() {

        acao = new Acao();

        RequestContext requestContext = RequestContext.getCurrentInstance();
        requestContext.execute("dlgAcao.hide()");
        requestContext.update("formAcao:dtAcoes");

    }

    //
    //get's do SelectItem
    //
    public List<SelectItem> getUnidadesOrcamentarias() {

        List<UnidadeOrcamentaria> uos = new UnidadeOrcamentariaDAO()
                .listarUnidadesOrcamentarias();

        if (uos != null) {

            unidadesOrcamentarias = new LinkedList<SelectItem>();

            for (UnidadeOrcamentaria uo : uos) {
                unidadesOrcamentarias.add(new SelectItem(uo, uo.toString()));
            }
        }

        return unidadesOrcamentarias;
    }

    public List<SelectItem> getFormasImplementacaoDaAcao() {
        if (formasImplementacaoDaAcao == null) {

            List<FormaDeImplementacaoDaAcao> fias = new FormaDeImplementacaoDaAcaoDAO()
                    .listarFormasDeImplementacaoDaAcao();

            if (fias != null) {

                formasImplementacaoDaAcao = new LinkedList<SelectItem>();

                for (FormaDeImplementacaoDaAcao fia : fias) {
                    formasImplementacaoDaAcao.add(new SelectItem(fia, fia.toString()));
                }
            }

        }
        return formasImplementacaoDaAcao;
    }

    public List<SelectItem> getTiposAcao() {

        if (tiposAcao == null) {

            List<TipoDeAcao> tas = new TipoDeAcaoDAO().listarTiposAcoes();

            if (tas != null) {

                tiposAcao = new LinkedList<SelectItem>();

                for (TipoDeAcao tipoDeAcao : tas) {
                    tiposAcao.add(new SelectItem(tipoDeAcao, tipoDeAcao.toString()));
                }

            }

        }

        return tiposAcao;
    }

    public List<SelectItem> getGestores() {

        List<Gestor> ges = new GestorDAO().listarGestores();

        if (ges != null) {

            gestores = new LinkedList<SelectItem>();

            for (Gestor g : ges) {
                gestores.add(new SelectItem(g, g.getNome()));
            }
        }

        return gestores;
    }

    public List<SelectItem> getUnidadesDeMedida() {

        List<UnidadeDeMedida> ums = new UnidadeDeMedidaDAO()
                .listarUnidadesDeMedida();

        if (ums != null) {

            unidadesDeMedida = new LinkedList<SelectItem>();

            for (UnidadeDeMedida um : ums) {
                unidadesDeMedida.add(new SelectItem(um, um.toString()));
            }
        }

        return unidadesDeMedida;
    }

    public List<SelectItem> getSubFuncoes() {

        List<SubFuncao> sfs = new SubFuncaoDAO()
                .listarSubFuncoes(programaBean.getPrograma().getFuncao());

        if (sfs != null) {

            subFuncoes = new LinkedList<SelectItem>();

            for (SubFuncao sf : sfs) {
                subFuncoes.add(new SelectItem(sf, sf.toString()));
            }

        }

        return subFuncoes;
    }

    //--------------------------------------------------------------------------
}
